package com.easylinkin.linkappapi.hcmy.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.hcmy.entity.AreasourceecologyDictionaryFunctionData;
import com.easylinkin.linkappapi.hcmy.entity.AreasourceecologyFunction;
import com.easylinkin.linkappapi.hcmy.entity.AreasourceecologyMenu;
import com.easylinkin.linkappapi.hcmy.mapper.AreasourceecologyDictionaryFunctionDataMapper;
import com.easylinkin.linkappapi.hcmy.mapper.AreasourceecologyFunctionMapper;
import com.easylinkin.linkappapi.hcmy.service.AreasourceecologyFunctionService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.space.mapper.LinkappAreaMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AreasourceecologyFunctionServiceImpl extends ServiceImpl<AreasourceecologyFunctionMapper, AreasourceecologyFunction> implements AreasourceecologyFunctionService{
    @Resource
    LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    AreasourceecologyDictionaryFunctionDataMapper dictionaryFunctionDataMapper;

    /***
     * 分页查询
     * @param page
     * @param areasourceecologyFunction
     * @return
     */
    @Override
    public IPage<AreasourceecologyFunction> page(Page page, AreasourceecologyFunction areasourceecologyFunction) {
        Assert.notNull(areasourceecologyFunction.getType(), "type 不能为空");
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        Integer type=areasourceecologyFunction.getType();
        areasourceecologyFunction.setTenantId(tenantId);
        //前置处理
        dataConvertBefore(areasourceecologyFunction);
        IPage resultPage=baseMapper.findAreasourceecologyList(page,areasourceecologyFunction);
        List<AreasourceecologyFunction> records = resultPage.getRecords();
        if(records == null || records.size()<=0){
            return resultPage;
        }
        Set<Integer> collect = records.stream().map(AreasourceecologyFunction::getId).collect(Collectors.toSet());
        List<LinkedHashMap<String, BigDecimal>> functionData = baseMapper.findFunctionData(StringUtils.join(collect, ","),areasourceecologyFunction.getType());

        Map<Integer, LinkedHashMap<String, BigDecimal>> functionDataMap=null;
        if(functionData != null && functionData.size()>0){
            functionDataMap = functionData.stream().filter(m -> m.get("id") != null).collect(Collectors.toMap(m -> Integer.valueOf(String.valueOf(m.get("id"))), m -> m, (k1, k2) -> k2));
        }
        Map<Integer, LinkedHashMap<String, BigDecimal>> finalFunctionDataMap = functionDataMap;
        records = records.stream().map(m -> {
            if (finalFunctionDataMap == null|| finalFunctionDataMap.get(m.getId()) == null) {
                return m;
            }
            finalFunctionDataMap.remove("id");
            m.setDataMap(finalFunctionDataMap.get(m.getId()));
            return m;
        }).collect(Collectors.toList());
        //后置处理
        dataConvertAfeter(records,type);
        resultPage.setRecords(records);
        return resultPage;
    }

    /***
     * 添加或者修改
     * @param areasourceecologyFunction
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateEntity(AreasourceecologyFunction areasourceecologyFunction){
        Assert.notNull(areasourceecologyFunction,"参数不能为空" );
        Assert.notNull(areasourceecologyFunction.getType(), "type 不能为空");
        Assert.notNull(areasourceecologyFunction.getYear(), "year 不能为空");
        LinkappUser notNullCurrent = linkappUserContextProducer.getNotNullCurrent();
        areasourceecologyFunction.setTenantId(notNullCurrent.getTenantId());
        repeatValidate(areasourceecologyFunction);
        //通过type 查找菜单
        List<AreasourceecologyMenu> menuByType = baseMapper.findMenuByType(areasourceecologyFunction.getType());
        if(menuByType == null || menuByType.size()<=0){
            log.error("面源菜单查询为空 type:"+areasourceecologyFunction.getType() );
            return;
        }
        ArrayList<AreasourceecologyDictionaryFunctionData> functionData = new ArrayList<>();
        Set<Integer> collect = menuByType.stream().map(AreasourceecologyMenu::getId).collect(Collectors.toSet());
        if(areasourceecologyFunction.getDataMap() != null && areasourceecologyFunction.getDataMap().size()>0){
            areasourceecologyFunction.getDataMap().entrySet().stream().filter(m-> !org.springframework.util.StringUtils.isEmpty(m.getValue())).forEach(m->{
                Integer type = Integer.valueOf(m.getKey());
                if(type == null || !collect.contains(type)){
                    throw new IllegalArgumentException("数据类型["+type+"]不存在");
                }
                AreasourceecologyDictionaryFunctionData data = new AreasourceecologyDictionaryFunctionData();
                data.setMenuId(type);
                data.setNumber(BigDecimal.valueOf(Double.valueOf(String.valueOf(m.getValue()))));
                functionData.add(data);
            });
        }
        LocalDateTime now = LocalDateTime.now();
        areasourceecologyFunction.setModifier(notNullCurrent.getId()+"");
        areasourceecologyFunction.setModifyTime(now);
        if(areasourceecologyFunction.getId() != null){
            //修改先删除子集
            areasourceecologyFunction.setIds(Arrays.asList(areasourceecologyFunction.getId()));
            deleteDataByIds(areasourceecologyFunction);
        }else{
            areasourceecologyFunction.setCreateTime(now);
            areasourceecologyFunction.setCreator(notNullCurrent.getId()+"");
        }
        //保存
        saveOrUpdate(areasourceecologyFunction);
        //保存子数据
        if(functionData != null && functionData.size()>0){
            List<AreasourceecologyDictionaryFunctionData> inertList = functionData.stream().map(m -> {
                m.setFunctionId(areasourceecologyFunction.getId());
                return m;
            }).collect(Collectors.toList());
            dictionaryFunctionDataMapper.batchInsert(inertList);
        }
    }


    /***
     * 删除
     * @param areasourceecologyFunction
     */
    @Override
    public void deleteByIds(AreasourceecologyFunction areasourceecologyFunction){
        Assert.notNull(areasourceecologyFunction,"参数不能为空" );
        Assert.notEmpty(areasourceecologyFunction.getIds(), "ids 不能为空");
        //删除
        removeByIds(areasourceecologyFunction.getIds());
        //删除子集合
        deleteDataByIds(areasourceecologyFunction);
    }

    /***
     * 根据类型查询菜单
     * @param areasourceecologyFunction
     * @return
     */
    @Override
    public List<AreasourceecologyMenu>  findMenuByType(AreasourceecologyFunction areasourceecologyFunction){
        Assert.notNull(areasourceecologyFunction,"参数不能为空" );
        Assert.notNull(areasourceecologyFunction.getType(),"type不能为空" );
        return baseMapper.findMenuByType(areasourceecologyFunction.getType());
    }

    /***
     * 前置处理
     * @param areasourceecologyFunction
     */
    private void dataConvertBefore(AreasourceecologyFunction areasourceecologyFunction){
        if(areasourceecologyFunction.getType() == 4){
            //施肥流失量->土地利用
            areasourceecologyFunction.setType(1);
        }
    }

    /***
     * 后置处理
     * @param type
     */
    private void dataConvertAfeter(List<AreasourceecologyFunction> records,Integer type){
        List<AreasourceecologyMenu> menuByType = baseMapper.findMenuByType(type);
        if(menuByType == null || menuByType.size()<=0){
            return;
        }
        Map<String, AreasourceecologyMenu> menuMap = menuByType.stream().collect(Collectors.toMap(m -> m.getDictionaryName(), m -> m, (k1, k2) -> k2,LinkedHashMap::new));
        if(type == 4){
            //施肥流失量
            fertilizerDrain(records,menuMap);
        }
    }

    /***
     * 肥料流失
     */
    private void fertilizerDrain(List<AreasourceecologyFunction> records,Map<String, AreasourceecologyMenu> menuMap){
        records=records.stream().map(m->{
            LinkedHashMap<String, BigDecimal> dataMap = m.getDataMap();
            if(dataMap == null){
                return m;
            }
            LinkedHashMap<String, BigDecimal> dataMapCopy=new LinkedHashMap<>();
            dataMap = dataMap.entrySet().stream().filter(data -> menuMap.get(data.getKey()) != null).collect(Collectors.toMap(data -> data.getKey(), data -> data.getValue(), (k1, k2) -> k2,LinkedHashMap::new));
            AtomicReference<String> menu=new AtomicReference<>();
            LinkedHashMap<String, BigDecimal> finalDataMap = dataMap;
            menuMap.entrySet().stream().forEach(data->{
                if(finalDataMap.get(data.getKey()) != null){
                    menu.set(data.getKey());
                    dataMapCopy.put(data.getKey(), finalDataMap.get(data.getKey()));
                    return;
                }
                    AreasourceecologyMenu value = data.getValue();
                    Object o = finalDataMap.get(menu.get());
                    if(o == null){
                        return;
                    }
                    BigDecimal num = (BigDecimal)o;
                    if(value.getDictionaryId() == 77){
                        num=num.multiply(BigDecimal.valueOf(0.933));
                    }
                    if(value.getDictionaryId() == 78){
                        num=num.multiply(BigDecimal.valueOf(0.077));
                    }
                    if(value.getDictionaryId() == 79){
                        num=num.multiply(BigDecimal.valueOf(1.233));
                    }
                    if(value.getDictionaryId() == 80){
                        num=num.multiply(BigDecimal.valueOf(0.389));
                    }
                    num = num.divide(BigDecimal.valueOf(1000), 3, BigDecimal.ROUND_HALF_UP);
                    dataMapCopy.put(data.getKey(), num);
            });
            m.setDataMap(dataMapCopy);
            return m;
        }).collect(Collectors.toList());
    }

    /***
     * 删除子集合
     * @param areasourceecologyFunction
     */
    private void deleteDataByIds(AreasourceecologyFunction areasourceecologyFunction){
        new LambdaUpdateChainWrapper<>(dictionaryFunctionDataMapper)
                .in(AreasourceecologyDictionaryFunctionData::getFunctionId, areasourceecologyFunction.getIds())
                .remove();
    }


    /***
     * 效验重复
     * @param areasourceecologyFunction
     */
    private void repeatValidate(AreasourceecologyFunction areasourceecologyFunction){
        Integer count = new LambdaQueryChainWrapper<>(baseMapper)
                .eq(AreasourceecologyFunction::getType,areasourceecologyFunction.getType() )
                .eq(AreasourceecologyFunction::getTenantId,areasourceecologyFunction.getTenantId())
                .eq(AreasourceecologyFunction::getYear, areasourceecologyFunction.getYear())
                .like(AreasourceecologyFunction::getAreaIds, areasourceecologyFunction.getAreaIds())
                .ne(areasourceecologyFunction.getId() != null, AreasourceecologyFunction::getId, areasourceecologyFunction.getId())
                .count();
        if(count == null || count<=0){
            return;
        }
        throw new IllegalArgumentException(""+areasourceecologyFunction.getYear()+"年度示范村存在重复");
    }
}
